/* libfake437 - a library for the rendering of code page 437 `graphics'
 * Copyright (C) 2008 Jack Kelly <endgame.dos@gmail.com>
 *
 * This program is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation, either version 3 of
 * the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef FAKE437_H
#define FAKE437_H

#include <SDL.h>

#define F437_NUM_CHARS 256
#define F437_NUM_COLORS 16
#define F437_CHAR_WIDTH 8
#define F437_CHAR_HEIGHT 14
#define F437_DEFAULT_WIDTH 80
#define F437_DEFAULT_HEIGHT 25
#define F437_DEFAULT_WIDTH_PX (F437_DEFAULT_WIDTH * F437_CHAR_WIDTH)
#define F437_DEFAULT_HEIGHT_PX (F437_DEFAULT_HEIGHT * F437_CHAR_HEIGHT)

/* Characters can be redefined in a similar manner to the CALL CHAR
 * command on a TI 99/4a. Consider an 8x14 grid for each cell:
 *
 *    84218421
 * 00|        | = 00
 * 01|        | = 00
 * 02| ###### | = 7E
 * 03|#      #| = 81
 * 04|# #  # #| = A5
 * 05|#      #| = 81
 * 06|#      #| = 81
 * 07|# #### #| = BD
 * 08|#  ##  #| = 99
 * 09|#      #| = 81
 * 10| ###### | = 7E
 * 11|        | = 00
 * 12|        | = 00
 * 13|        | = 00
 *
 * So the full char definition is "00007E81A58181BD99817E000000"
 */
typedef char f437_charDef[F437_NUM_CHARS][(F437_CHAR_WIDTH/4)*F437_CHAR_HEIGHT];
typedef SDL_Color f437_colorDef[F437_NUM_COLORS];

/* Cell colors are indexes into the FAKE437.colors table. */
struct f437_cell{
  Uint8 ch;
  Uint8 fg;
  Uint8 bg;
};

typedef struct{
  f437_charDef chars;
  f437_colorDef colors;
  Uint16 width;
  Uint16 height;
  struct f437_cell *cells;
  Uint8 *dirty_cells;
  SDL_Surface *surface;
} FAKE437;

#define F437_INDEX(f437, x, y) (((f437->width)*(y)) + (x))

/* Turn a given SDL_Surface into a FAKE437 structure representing a
 * grid of given dimensions. The cells are centred in the surface if
 * the surface is too large. NULL is returned on error, or if too many
 * rows or columns are requested.
 */
extern FAKE437 *f437_Create(SDL_Surface *surface, Uint16 width, Uint16 height);
extern SDL_Surface *f437_Destroy(FAKE437 *fake437);

extern void f437_RedefineChar(FAKE437 *fake437, Uint8 ch, const char *newCh);
extern void f437_RedefineColor(FAKE437 *fake437, Uint8 col,
			       const SDL_Color *newCol);
extern void f437_SetChar(FAKE437 *fake437, Uint16 x, Uint16 y, Uint8 ch);
extern void f437_SetForeground(FAKE437 *fake437, Uint16 x, Uint16 y, Uint8 fg);
extern void f437_SetBackground(FAKE437 *fake437, Uint16 x, Uint16 y, Uint8 bg);
extern void f437_SetCharColor(FAKE437 *fake437, Uint16 x, Uint16 y,
			      Uint8 ch, Uint8 fg, Uint8 bg);
extern void f437_SetCharDefs(FAKE437 *fake437, f437_charDef *chars);
extern void f437_SetColorDefs(FAKE437 *fake437, f437_colorDef *colors);

extern Uint8 f437_GetChar(FAKE437 *fake437, Uint16 x, Uint16 y);
extern Uint8 f437_GetForeground(FAKE437 *fake437, Uint16 x, Uint16 y);
extern Uint8 f437_GetBackground(FAKE437 *fake437, Uint16 x, Uint16 y);
extern void f437_GetCharDefs(FAKE437 *fake437, f437_charDef *chars);
extern void f437_GetColorDefs(FAKE437 *fake437, f437_colorDef *colors);
/* Get the offsets at which the cells are being drawn in the wrapped
 * surface.
 */
extern void f437_GetOffsets(FAKE437 *fake437, Sint16 *offsetx, Sint16 *offsety);
/* Get the coordinates of the cell containing the given pixel. If the
 * pixel is outside of the area used for cells (e.g., when the surface
 * is too large), -1 is returned.
 */
extern void f437_GetCellCoords(FAKE437 *fake437, Uint16 x, Uint16 y,
			       Sint16 *out_x, Sint16 *out_y);

extern void f437_Update(FAKE437 *fake437);
/* The array of rects is heap-allocated and expected to be freed by
 * the caller. numrects is an output parameter, and if numrects != 0
 * and this returns NULL, something's gone wrong.
 */
extern SDL_Rect *f437_GetDirtyRects(FAKE437 *fake437, int *numrects);

#endif
